import time
from datetime import datetime, timedelta

from info import db
from info.modules import user, news
from info.modules.admin import admin_blu

# 后台登陆
from flask import request, render_template, current_app, url_for, redirect, session, g, abort, jsonify

from info.utils.common import user_login_data, file_upload
from info.utils.constants import USER_COLLECTION_MAX_NEWS, QINIU_DOMIN_PREFIX
from info.utils.models import User, News, Category

# 后台登陆
from info.utils.response_code import RET, error_map


@admin_blu.route('/login', methods=["GET", "POST"])
def login():
    # GET展示页面
    if request.method == "GET":
        # 取出session数据    #如果用户已经登陆，下次登陆将免密码
        user_id = session.get("user_id")
        is_admin = session.get("is_admin")
        if user_id and is_admin:  # 管理员已登陆，重定向到后台首页
            return redirect(url_for("admin.index"))
        return render_template("admin/login.html")

    # POST
    # 1获取参数
    username = request.form.get("username")
    password = request.form.get("password")

    # 2校验参数
    if not all([username, password]):
        return render_template("admin/login.html", errmsg="参数不足")
    # 3获取管理员用户数据
    try:  # is_admin==True/是管理员
        user = User.query.filter(User.mobile == username, User.is_admin == True).first()
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return render_template("admin/login.html", errmsg="数据库操作失败")
    # 判断用户是否存在
    if not user:
        return render_template("admin/login.html", errmsg="管理员不存在")

    # 4校验参数
    if not user.check_password(password):
        return render_template("admin/login.html", errmsg="账号。密码错误")

    # 保存session数据，实现免密码登陆
    session['user_id'] = user.id
    session['is_admin'] = True

    # 5校验成功，重定向到后台首页
    return redirect(url_for("admin.index"))


# 后台退出登陆
@admin_blu.route("/")
def logout():
    session.pop("user_id", None)
    session.pop("is_admin", None)
    # 重定向到后台登陆
    return redirect(url_for("admin.login"))


# 后台首页
@admin_blu.route('/index')
@user_login_data
def index():
    return render_template("admin/index.html", user=g.user.to_dict())


# 用户统计
@admin_blu.route("/user_count")
def user_count():
    # 1查询用户总数
    try:
        total_count = User.query.filter(User.is_admin == False).count()
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        total_count = 0

    # 2查询月新增人数    #注册时间是本月1号 0点

    # 获取当前时间的年和月
    t = time.localtime()

    # 构建日记字符串 2019-01-01
    # mon_date_str = "2019-01-01"
    mon_date_str = "%d-%02d-01" % (t.tm_year, t.tm_mon)
    # 将字符串转换成日期对象    datetime/内置函数方法
    mon_date = datetime.strptime(mon_date_str, "%Y-%m-%d")
    try:  # create_time当前日期对象，所有需要对象做比较，不能是字符串
        mon_count = User.query.filter(User.is_admin == False, User.create_time >= mon_date).count()
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        mon_count = 0

    # 3查询日新增人数
    # 构建日期字符串 2019-01-05
    dat_date_str = "%d-%02d-%02d" % (t.tm_year, t.tm_mon, t.tm_mday)

    # 获取日期字符串对象
    day_date = datetime.strptime(dat_date_str, "%Y-%m-%d")

    try:  # create_time当前日期对象，所有需要对象做比较，不能是字符串
        day_count = User.query.filter(User.is_admin == False, User.create_time >= day_date).count()
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        day_count = 0

    # 6曲线图设置------------------->
    # 某日的注册人数   注册时间 >= 当日0点，<次日0点
    # 添加对象
    active_count = []
    active_time = []
    for i in range(0, 30):
        begin_date = day_date - timedelta(days=i)  # 当日0点
        end_date = begin_date + timedelta(days=1)  # 次日0点

        try:  # create_time当前日期对象，所有需要对象做比较，不能是字符串
            one_dat_count = User.query.filter(User.is_admin == False, User.create_time >= begin_date,
                                              User.create_time < end_date).count()

            # 添加进列表对象
            active_count.append(one_dat_count)  # 储存日期对象

            # 将日期对象转为日期字符串
            one_day_str = begin_date.strftime("%Y-%m-%d")
            active_time.append(one_day_str)  # 存放日期字符串

        except BaseException as e:
            # 包装进日记做记录
            current_app.logger.error(e)
            one_dat_count = 0

    # 日期和注册倒序
    active_time.reverse()
    active_count.reverse()

    # 4添加字典封装数据方便取出
    data = {
        "total_count": total_count,
        "mon_count": mon_count,
        "day_count": day_count,
        "active_count": active_count,
        "active_time": active_time
    }

    # 5模板传入进前端
    return render_template("admin/user_count.html", data=data)


# 用户列表
@admin_blu.route('/user_list')
def user_list():
    # 1获取参数
    p = request.args.get("p", 1)

    # 2校验参数
    try:
        p = int(p)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(403)

    # 3查询所有用户的收藏新闻  分页查询  收藏时间倒序
    try:
        pn = User.query.paginate(p, USER_COLLECTION_MAX_NEWS)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(500)

    data = {
        "user_list": [user.to_admin_dict() for user in pn.items],
        "total_page": pn.pages,
        "cur_page": pn.page
    }

    # 4数据传入模板渲染
    return render_template("admin/user_list.html", data=data)


# 审核列表
@admin_blu.route('/news_review')
def news_review():
    # 1获取参数
    p = request.args.get("p", 1)
    keyword = request.args.get("keyword")

    # 2校验参数
    try:
        p = int(p)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(403)
    # 数据封装进列表
    filter_list = []
    if keyword:  # 搜索
        filter_list.append(News.title.contains(keyword))

    # 3查询所有新闻数据  分页查询  收藏时间倒序
    try:
        pn = News.query.filter(*filter_list).paginate(p, USER_COLLECTION_MAX_NEWS)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(500)

    data = {
        "news_list": [news.to_review_dict() for news in pn.items],
        "total_page": pn.pages,
        "cur_page": pn.page
    }

    # 4数据传入模板渲染
    return render_template("admin/news_review.html", data=data)


# 审核详情
@admin_blu.route("/news_review_detail/<int:news_id>")
def news_review_detail(news_id):
    # 根据新闻id查询新闻数据
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(500)
    # 传入模板渲染
    return render_template("admin/news_review_detail.html", news=news.to_dict())


# 新闻提交审核
@admin_blu.route("/news_review_action", methods=["POST"])
def news_review_action():
    # 1获取参数
    news_id = request.json.get("news_id")
    action = request.json.get("action")
    reason = request.json.get("reason")

    # 2校验参数
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    # 查看判断参数
    if action not in ["accept", "reject"]:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    try:
        news_id = int(news_id)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    # 3获取新闻数据
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    # 4根据action修改新闻状态
    if action == "accept":
        news.status = 0
    else:  # 返回拒绝原因
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档
        news.reason = reason
        news.status = -1

    # 5返回json
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])  # 与前段定义的规则包文档


# 编辑列表
@admin_blu.route('/news_edit')
def news_edit():
    # 1获取参数
    p = request.args.get("p", 1)
    keyword = request.args.get("keyword")

    # 2校验参数
    try:
        p = int(p)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(403)
    # 数据封装进列表
    filter_list = []
    if keyword:  # 搜索
        filter_list.append(News.title.contains(keyword))

    # 3查询所有新闻数据  分页查询  收藏时间倒序
    try:
        pn = News.query.filter(*filter_list).paginate(p, USER_COLLECTION_MAX_NEWS)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(500)

    data = {
        "news_list": [news.to_review_dict() for news in pn.items],
        "total_page": pn.pages,
        "cur_page": pn.page
    }

    # 4数据传入模板渲染
    return render_template("admin/news_edit.html", data=data)


# 编辑详情
#分开做的GET/POST
@admin_blu.route("/news_edit_detail")
def news_edit_detail():
    # 1获取参数
    news_id = request.args.get("news_id")

    # 2校验参数
    try:
        news_id = int(news_id)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(403)

    # 3根据新闻id查询新闻数据
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(500)

    # 4查询所有分类
    try:
        categories = Category.query.filter(Category.id != 1).all()
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return abort(500)

    # 5标识新闻当前的分类
    # #将数据放进列表
    category_list = []
    # 遍历id取出对应的
    for category in categories:
        category_dict = category.to_dict()
        is_selected = False
        if category.id == news.category_id:
            is_selected = True
        ##将数据放进列表方便渲染
        category_dict["is_selected"] = is_selected
        category_list.append(category_dict)

    # 6传入模板渲染返回
    return render_template("admin/news_edit_detail.html", news=news.to_dict(), category_list=category_list)


# 编辑详情页POST提交
#分开做的GET/POST
@admin_blu.route("/news_edit_detail", methods=["POST"])
def news_edit_detail_post():  # 一个路由可以分成多个视图函数来完成不同的请求方式处理，视图/函数名字不能相同，蓝图名/路径名相同
    # 1获取参数
    news_id = request.form.get("news_id")
    title = request.form.get("title")
    category_id = request.form.get("category_id")
    digest = request.form.get("digest")
    content = request.form.get("content")
    index_image = request.files.get("index_image")

    # 2校验参数
    if not all([news_id, title, category_id, digest, content]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    try:
        news_id = int(news_id)
        category_id = int(category_id)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    # 3查询获取新闻数据
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        # 包装进日记做记录
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])  # 与前段定义的规则包文档

    # 4修改新闻数据
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.content = content
    if index_image:
        try:
            # 读取类容
            img_bytes = index_image.read()
            # 上传到气牛云
            file_name = file_upload(img_bytes)
            news.index_image_url = QINIU_DOMIN_PREFIX + file_name
        except BaseException as e:
            # 包装进日记做记录
            current_app.logger.error(e)
            return jsonify(errno=RET.THIRDERR, errmsg=error_map[RET.THIRDERR])  # 与前段定义的规则包文档

    # 5json返回
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])  # 与前段定义的规则包文档



#新闻分类
@admin_blu.route("/news_type", methods=["GET","POST"])
def news_type():
    if request.method=="GET":
        #查询所有分类数据
        try:
            categories=Category.query.filter(Category.id!=1).all()
        except BaseException as e:
            #包装进日记做记录
            current_app.logger.error(e)
            return abort(500)
        #查询出来的数据传入模板渲染
        return render_template("admin/news_type.html",categories=categories)

    #POST处理
    id =request.json.get("id")
    name=request.json.get("name")
    if not name:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    #修改分类
    if id:
        try:
            id =int(id)
            category=Category.query.get(id)
            category.name=name
        except BaseException as e:
            #包装进日记做记录
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])  # 与前段定义的规则包文档

    else:   #新增分类
        new_category=Category(name=name)
        #数据库自动提交
        db.session.add(new_category)
    #json返回数据
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])  # 与前段定义的规则包文档





















